<?php

/**
 * 启动计时器
 */
function timer_start() {
    global $timestart;
    $mtime = explode(' ', microtime());
    $mtime = $mtime[1] + $mtime[0];
    $timestart = $mtime;
    return true;
}

/**
 * 停止计时器，返回时间消耗，并可显示输出
 * @param $display
 * @param $precision
 */
function timer_stop($display = 0, $precision = 3) {
    global $timestart, $timeend;
    $mtime = microtime();
    $mtime = explode(' ', $mtime);
    $mtime = $mtime[1] + $mtime[0];
    $timeend = $mtime;
    $timetotal = $timeend - $timestart;
    $r = number_format($timetotal, $precision);
    if ($display)
        echo $r;
    return $r;
}

/**
 * 测试输出变量
 * @param $var
 */
function debug($var = null) {
    echo '<pre>';
    if ($var === null) {
        print_r($GLOBALS);
    } else {
        print_r($var);
    }
    exit();
}

/**
 * 对象克隆
 * @param $object
 */
function cb_clone($object) {
    static $can_clone;
    if (!isset($can_clone)) {
        $can_clone = version_compare(phpversion(), '5.0', '>=');
    }
    return $can_clone ? clone( $object ) : $object;
}

/**
 * 检测是否为cb_Error对象
 * @param $thing
 */
function is_cb_error($thing) {
    if (is_object($thing) && is_a($thing, 'cb_Error'))
        return true;
    return false;
}

/**
 * 备用翻译函数
 * @param $str
 */
function __($str) {
    return $str;
}

/**
 * 返回数据库查询次数
 */
function get_num_queries() {
    global $cbdb;
    return $cbdb->get_num_queries();
}

/**
 * 返回HTTP状态的描述信息
 *
 * @param int $code HTTP status code.
 * @return string
 */
function get_status_header_desc($code) {
    global $cb_header_to_desc;

    $code = abs(intval($code));

    if (!isset($cb_header_to_desc)) {
        $cb_header_to_desc = array(
            100 => 'Continue',
            101 => 'Switching Protocols',
            102 => 'Processing',
            200 => 'OK',
            201 => 'Created',
            202 => 'Accepted',
            203 => 'Non-Authoritative Information',
            204 => 'No Content',
            205 => 'Reset Content',
            206 => 'Partial Content',
            207 => 'Multi-Status',
            226 => 'IM Used',
            300 => 'Multiple Choices',
            301 => 'Moved Permanently',
            302 => 'Found',
            303 => 'See Other',
            304 => 'Not Modified',
            305 => 'Use Proxy',
            306 => 'Reserved',
            307 => 'Temporary Redirect',
            400 => 'Bad Request',
            401 => 'Unauthorized',
            402 => 'Payment Required',
            403 => 'Forbidden',
            404 => 'Not Found',
            405 => 'Method Not Allowed',
            406 => 'Not Acceptable',
            407 => 'Proxy Authentication Required',
            408 => 'Request Timeout',
            409 => 'Conflict',
            410 => 'Gone',
            411 => 'Length Required',
            412 => 'Precondition Failed',
            413 => 'Request Entity Too Large',
            414 => 'Request-URI Too Long',
            415 => 'Unsupported Media Type',
            416 => 'Requested Range Not Satisfiable',
            417 => 'Expectation Failed',
            422 => 'Unprocessable Entity',
            423 => 'Locked',
            424 => 'Failed Dependency',
            426 => 'Upgrade Required',
            500 => 'Internal Server Error',
            501 => 'Not Implemented',
            502 => 'Bad Gateway',
            503 => 'Service Unavailable',
            504 => 'Gateway Timeout',
            505 => 'HTTP Version Not Supported',
            506 => 'Variant Also Negotiates',
            507 => 'Insufficient Storage',
            510 => 'Not Extended'
        );
    }

    if (isset($cb_header_to_desc[$code]))
        return $cb_header_to_desc[$code];
    else
        return '';
}

/**
 * 设定特定的HTTP状态头.
 *
 * @param int $header HTTP status code
 * @return unknown
 */
function status_header($header) {
    $text = get_status_header_desc($header);

    if (empty($text))
        return false;

    $protocol = $_SERVER["SERVER_PROTOCOL"];
    if ('HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol)
        $protocol = 'HTTP/1.0';
    $status_header = "$protocol $header $text";

    return @header($status_header, true, $header);
}

/**
 * 发送不缓存的HTTP状态
 */
function nocache_headers() {
    $headers = array(
        'Expires' => 'Wed, 11 Jan 1984 05:00:00 GMT',
        'Last-Modified' => gmdate('D, d M Y H:i:s') . ' GMT',
        'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
        'Pragma' => 'no-cache',
    );
    foreach ((array) $headers as $name => $field_value)
        @header("{$name}: {$field_value}");
}

/**
 * 宕掉系统，并给出提示。
 * @param unknown_type $message
 * @param unknown_type $title
 * @param unknown_type $args
 */
function cb_die($message, $title = '', $args = array()) {
    $defaults = array('response' => 500);
    $r = cb_parse_args($args, $defaults);

    $have_gettext = function_exists('__');

    if (function_exists('is_cb_error') && is_cb_error($message)) {
        if (empty($title)) {
            $error_data = $message->get_error_data();
            if (is_array($error_data) && isset($error_data['title']))
                $title = $error_data['title'];
        }
        $errors = $message->get_error_messages();
        switch (count($errors)) :
            case 0 :
                $message = '';
                break;
            case 1 :
                $message = "<p>{$errors[0]}</p>";
                break;
            default :
                $message = "<ul>\n\t\t<li>" . join("</li>\n\t\t<li>", $errors) . "</li>\n\t</ul>";
                break;
        endswitch;
    } elseif (is_string($message)) {
        $message = "<p>$message</p>";
    }

    if (isset($r['back_link']) && $r['back_link']) {
        $back_text = $have_gettext ? __('&laquo; 返回') : '&laquo; 返回';
        $message .= "\n<p><a href='javascript:history.back()'>$back_text</p>";
    }

    if (!headers_sent()) {
        status_header($r['response']);
        nocache_headers();
        header('Content-Type: text/html; charset=utf-8');
    }

    if (empty($title)) {
        $title = $have_gettext ? __(SITE_NAME . ' &rsaquo; 系统错误') : SITE_NAME . '&rsaquo; 系统错误';
    }
?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
            <title><?php echo $title ?></title>
        </head>
        <body id="error-page">
        <?php echo $message; ?>
    </body>
</html>
<?php
        die();
    }

    /**
     * 加载自定义数据库错误或显示 CityBao DB 错误.
     *
     * @uses $cbdb
     */
    function dead_db() {
        global $cbdb;

        // 如果存在自定义数据库错误信息，则显示它
        if (file_exists(CB_ROOT . 'db-error.php')) {
            require_once( CB_ROOT . 'db-error.php' );
            die();
        }

        // 如果正在安装，或在后台管理系统中，则显示详细错误
        if (defined('CB_INSTALLING') || defined('CB_ADMIN'))
            cb_die($cbdb->error);

        status_header(500);
        nocache_headers();
        header('Content-Type: text/html; charset=utf-8');
?>
        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
        <html xmlns="http://www.w3.org/1999/xhtml">
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
                <title>数据库错误</title>

            </head>
            <body>
                <h1>citybao:进行数据库连接时出现了错误，请与管理员联系</h1>
            </body>
        </html>
<?php
        die();
    }

    /**
     * 是否属于后台管理系统
     */
    function is_admin() {
        if (defined('CB_ADMIN'))
            return CB_ADMIN;
        return false;
    }

    /**
     * 格式化空白，转换换行符，删除多余空白
     * @param $str
     */
    function normalize_whitespace($str) {
        $str = trim($str);
        $str = str_replace("\r", "\n", $str);
        $str = preg_replace(array('/\n+/', '/[ \t]+/'), array("\n", ' '), $str);
        return $str;
    }

    /**
     * 删除所有HTML标签，所括script和style
     */
    function cb_strip_all_tags($string, $remove_breaks = false) {
        $string = preg_replace('@<(script|style)[^>]*?>.*?</\\1>@si', '', $string);
        $string = strip_tags($string);

        if ($remove_breaks)
            $string = preg_replace('/[\r\n\t ]+/', ' ', $string);

        return trim($string);
    }

    /**
     * 递归执行stripslashes
     * @param unknown_type $value
     * @return Ambigous <multitype:, string>
     */
    function stripslashes_deep($value) {
        if (is_array($value)) {
            $value = array_map('stripslashes_deep', $value);
        } elseif (is_object($value)) {
            $vars = get_object_vars($value);
            foreach ($vars as $key => $data) {
                $value->{$key} = stripslashes_deep($data);
            }
        } else {
            $value = stripslashes($value);
        }

        return $value;
    }

    function addslashes_gpc($gpc) {
        global $cbdb;
        if (get_magic_quotes_gpc ())
            $gpc = stripslashes($gpc);

        return $cbdb->escape($gpc);
    }

    /**
     * 递归执行addslashes
     * @param $array
     */
    function add_magic_quotes($array) {
        foreach ((array) $array as $k => $v) {
            if (is_array($v)) {
                $array[$k] = add_magic_quotes($v);
            } else {
                $array[$k] = addslashes($v);
            }
        }
        return $array;
    }

    function cb_parse_str($string, &$array) {
        parse_str($string, $array);
        if (get_magic_quotes_gpc ())
            $array = stripslashes_deep($array);
        $array = apply_filters('cb_parse_str', $array);
    }

    /**
     * Callback to convert URI match to HTML A element.
     *
     * @access private
     *
     * @param array $matches Single Regex Match.
     * @return string HTML A element with URI address.
     */
    function _make_url_clickable_cb($matches) {
        $url = $matches[2];
        if (empty($url))
            return $matches[0];

        return $matches[1] . "<a href=\"$url\" rel=\"nofollow\">$url</a>";
    }

    /**
     * Callback to convert URL match to HTML A element.
     *
     * @access private
     *
     * @param array $matches Single Regex Match.
     * @return string HTML A element with URL address.
     */
    function _make_web_ftp_clickable_cb($matches) {
        $ret = '';
        $dest = $matches[2];
        $dest = 'http://' . $dest;
        if (empty($dest))
            return $matches[0];

        // removed trailing [.,;:)] from URL
        if (in_array(substr($dest, -1), array('.', ',', ';', ':', ')')) === true) {
            $ret = substr($dest, -1);
            $dest = substr($dest, 0, strlen($dest) - 1);
        }
        return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>$ret";
    }

    /**
     * Callback to convert email address match to HTML A element.
     *
     * @access private
     *
     * @param array $matches Single Regex Match.
     * @return string HTML A element with email address.
     */
    function _make_email_clickable_cb($matches) {
        $email = $matches[2] . '@' . $matches[3];
        return $matches[1] . "<a href=\"mailto:$email\">$email</a>";
    }

    /**
     * Convert plaintext URI to HTML links.
     *
     * Converts URI, www and ftp, and email addresses. Finishes by fixing links
     * within links.
     *
     * @since 0.71
     *
     * @param string $ret Content to convert URIs.
     * @return string Content with converted URIs.
     */
    function make_clickable($ret) {
        $ret = ' ' . $ret;
        // in testing, using arrays here was found to be faster
        $ret = preg_replace_callback('#(?<=[\s>])(\()?([\w]+?://(?:[\w\\x80-\\xff\#$%&~/=?@\[\](+-]|[.,;:](?![\s<]|(\))?([\s]|$))|(?(1)\)(?![\s<.,;:]|$)|\)))+)#is', '_make_url_clickable_cb', $ret);
        $ret = preg_replace_callback('#([\s>])((www|ftp)\.[\w\\x80-\\xff\#$%&~/.\-;:=,?@\[\]+]+)#is', '_make_web_ftp_clickable_cb', $ret);
        $ret = preg_replace_callback('#([\s>])([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,})#i', '_make_email_clickable_cb', $ret);
        // this one is not in an array because we need it to run last, for cleanup of accidental links within links
        $ret = preg_replace("#(<a( [^>]+?>|>))<a [^>]+?>([^>]+?)</a></a>#i", "$1$3</a>", $ret);
        $ret = trim($ret);
        return $ret;
    }

    function cb_parse_args($args, $defaults = '') {
        if (is_object($args))
            $r = get_object_vars($args);
        elseif (is_array($args))
            $r = & $args;
        else
            cb_parse_str($args, $r);

        if (is_array($defaults))
            return array_merge($defaults, $r);
        return $r;
    }

    /**
     * 如果需要，就进行序列化
     *
     * @param mixed $data
     * @return mixed
     */
    function maybe_serialize($data) {
        if (is_array($data) || is_object($data))
            return serialize($data);

        if (is_serialized($data))
            return serialize($data);

        return $data;
    }

    /**
     * 当给定的参数是一个序列化串时，则反序列化
     *
     * @param string $original
     * @return mixed
     */
    function maybe_unserialize($original) {
        if (is_serialized($original))
            return @unserialize($original);
        return $original;
    }

    /**
     * 检查一个值是否被序列化了
     *
     * 如果给定的参数不是一个字符串的话，总是返回false
     *
     * @param mixed $data
     * @return bool
     */
    function is_serialized($data) {
        if (!is_string($data))
            return false;
        $data = trim($data);
        if ('N;' == $data)
            return true;
        if (!preg_match('/^([adObis]):/', $data, $badions))
            return false;
        switch ($badions[1]) {
            case 'a' :
            case 'O' :
            case 's' :
                if (preg_match("/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data))
                    return true;
                break;
            case 'b' :
            case 'i' :
            case 'd' :
                if (preg_match("/^{$badions[1]}:[0-9.E-]+;\$/", $data))
                    return true;
                break;
        }
        return false;
    }

    /**
     * 检查一个被序列化的值是否是字符串值
     *
     * @param mixed $data
     * @return bool
     */
    function is_serialized_string($data) {
        return false;
        $data = trim($data);
        if (preg_match('/^s:[0-9]+:.*;$/s', $data))
            return true;
        return false;
    }

    /**
     * 根据给定的路径，创建目录（多级创建）并尝试赋于权限
     *
     * @param string $target
     * @return bool
     */
    function cb_mkdir($target) {
        $target = str_replace('//', '/', $target);
        $target = rtrim($target, '/');
        if (empty($target))
            $target = '/';

        if (file_exists($target))
            return @is_dir($target);

        if (@mkdir($target)) {
            $stat = @stat(dirname($target));
            $dir_perms = $stat['mode'] & 0007777;
            @chmod($target, $dir_perms);
            return true;
        } elseif (is_dir(dirname($target))) {
            return false;
        }

        if (( $target != '/' ) && ( cb_mkdir(dirname($target)) ))
            return cb_mkdir($target);

        return false;
    }

    /**
     * 删除指定路径目录|文件，包括子目录和文件
     *
     * 如果是文件，直接删除，如果是目录，则删除该目录，包括子目录和文件
     *
     * @param String $path
     */
    function cb_unlink($path) {
        if (!file_exists($path))
            return false;
        if (is_file($path) || is_link($path))
            return @unlink($path);
        $files = scandir($path);
        foreach ($files as $filename) {
            if ($filename == '.' || $filename == '..')
                continue;
            $file = str_replace('//', '/', $path . '/' . $filename);
            cb_unlink($file);
        }
        if (!@rmdir($path))
            return false;
        return true;
    }

    /**
     * 显示错误或提示信息
     * @param $message
     * @param $forward
     * @param $title
     */
    function show_message($message, $forward='', $title = '提示信息') {
        global $config_core, $tpl;
        $tpl->assign('message', $message);
        $tpl->assign('title', $title);
        $tpl->assign('forward', $forward);
        $tpl->display('message.tpl');
        exit();
    }

    /**
     * 将数据库中取出地配置记录转化为KEY-VALUE数组
     *
     * @param $dbsettings
     */
    function normalizer_dbsettings($dbsettings) {
        $result = array();
        if (!is_array($dbsettings)) {
            return $result;
        }
        foreach ($dbsettings as $setting) {
            if (isset($setting['key']) && isset($setting['value'])) {
                $result[$setting['key']] = $setting['value'];
            }
        }
        return $result;
    }

    /**
     * 保存cookie
     * @param $var
     * @param $value
     * @param $time 保存时长
     */
    function set_cookie($var, $value = '', $time = 0) {
        $var = (string) $var;
        $time = $time > 0 ? TIME_STAMP + $time : (empty($value) ? TIME_STAMP - 3600 : 0);
        $port = $_SERVER['SERVER_PORT'] == '443' ? 1 : 0;
        $var = COOKIE_PREFIX . $var;
        $value = str_code(maybe_serialize($value));
        return setcookie($var, $value, $time, COOKIE_PATH, COOKIE_DOMAIN, $port);
    }

    /**
     * 取出cookie
     * @param $var
     */
    function get_cookie($var) {
        $var = (string) $var;
        $var = COOKIE_PREFIX . $var;
        $return = isset($_COOKIE[$var]) ? $_COOKIE[$var] : '';
        $return = maybe_unserialize(str_code($return, 'DECODE'));
        return $return;
    }

    /**
     * 可逆加密解密函数
     */
    function str_code($string, $action = 'ENCODE', $hash = '') {
        if (!defined('SECURE_AUTH_KEY'))
            define('SECURE_AUTH_KEY', 'citybao_str_code_str');
        $hash = empty($hash) ? SECURE_AUTH_KEY : $hash;
        $action != 'ENCODE' && $string = base64_decode($string);
        $code = '';
        $HTTP_USER_AGENT = str_replace(array(
                    '<',
                    '>',
                    '"',
                    "'",
                    '/',
                    ':',
                    ";",
                    ".",
                    "(",
                    ")",
                    '%3C',
                    '%3E',
                    '%22',
                    '%27',
                    '%3c',
                    '%3e'
                        ), '', $_SERVER['HTTP_USER_AGENT']);
        $key = substr(md5($HTTP_USER_AGENT . $hash), 8, 18);
        $keylen = strlen($key);
        $strlen = strlen($string);
        for ($i = 0; $i < $strlen; $i++) {
            $k = $i % $keylen;
            $code .= $string[$i] ^ $key[$k];
        }
        return ($action != 'DECODE' ? base64_encode($code) : $code);
    }

    /**
     * 获取IP地址
     */
    function getip() {
        if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
            $ip = getenv('HTTP_CLIENT_IP');
        } else
        if (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
            $ip = getenv('HTTP_X_FORWARDED_FOR');
        } else
        if (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
            $ip = getenv('REMOTE_ADDR');
        } else
        if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        $temp = array();
        preg_match("/[\d\.]{7,15}/", $ip, $temp);
        $ip = $temp[0] ? $temp[0] : 'unknown';
        unset($temp);
        return $ip;
    }

    /**
     * 生成密码令牌，用于自动生成密码
     */
    function genToken($len = 32, $md5 = true) {
        mt_srand((double) microtime () * 1000000);
        $chars = array('Q', '@', '8', 'y', '%', '^', '5', 'Z', '(', 'G', '_', 'O', '`', 'S', '-', 'N', '<', 'D', '{', '}', '[', ']', 'h', ';', 'W', '.', '/', '|', ':', '1', 'E', 'L', '4', '&', '6', '7', '#', '9', 'a', 'A', 'b', 'B', '~', 'C', 'd', '>', 'e', '2', 'f', 'P', 'g', ')', '?', 'H', 'i', 'X', 'U', 'J', 'k', 'r', 'l', '3', 't', 'M', 'n', '=', 'o', '+', 'p', 'F', 'q', '!', 'K', 'R', 's', 'c', 'm', 'T', 'v', 'j', 'u', 'V', 'w', ',', 'x', 'I', '$', 'Y', 'z', '*');
        $numChars = count($chars) - 1;
        $token = '';
        for ($i = 0; $i < $len; $i++)
            $token .= $chars [mt_rand(0, $numChars)];

        if ($md5) {
            $chunks = ceil(strlen($token) / 32);
            $md5token = '';
            for ($i = 1; $i <= $chunks; $i++)
                $md5token .= md5(substr($token, $i * 32 - 32, 32));
            $token = substr($md5token, 0, $len);
        }
        return $token;
    }

    /**
     * URL跳转
     * @param unknown_type $url
     */
    function redirect($url = '.') {
        header("Location:$url");
        exit();
    }

    /**
     * 表单来源验证字段的生成
     * @param string $action
     */
    function form_validate($action) {
        $action = (string) $action;
        return md5(md5($action . SECURE_AUTH_KEY . IP_ADDRESS . $_SERVER['HTTP_USER_AGENT']));
    }

    /**
     * 生成验证字串，并存入数据库
     * @param string $str 生成验证串的识别码
     * @param int    $lifetime 有效期（小时）
     * @param string $remark 描述
     */
    function get_validate_code($str = '', $lifetime = 48, $remark = '') {
        global $cbdb;
        $code = md5($str . TIME_STAMP . IP_ADDRESS);
        $lifetime = $lifetime < 1 ? 1 : $lifetime;
        $lifetime = $lifetime * 3600;
        $insert_data = array('code' => $code,
            'submitdate' => TIME_STAMP,
            'lifetime' => $lifetime,
            'remark' => $remark
        );
        $cbdb->insert('{#cbdbPrefix}validate', $insert_data);
        return $code;
    }

    /**
     * 验证验证字串
     * @param string $code 待验证字串
     * @param bool   $ifdelete 是否删除数据库记录
     * @return bool
     */
    function verify_validate_code($code, $ifdelete=true) {
        global $cbdb;
        $result = $cbdb->get_row('SELECT * FROM {#cbdbPrefix}validate WHERE code="' . $code . '" AND (' . TIME_STAMP . '-submitdate)<lifetime LIMIT 0,1');
        if ($ifdelete) {
            $sql = "DELETE FROM {#cbdbPrefix}validate WHERE code='" . $code . "' OR (" . TIME_STAMP . "-submitdate)>lifetime";
            $cbdb->query($sql);
        }
        return $result;
    }

    /**
     * 发送邮件
     * @param unknown_type $to
     * @param unknown_type $subject
     * @param unknown_type $message
     * @param unknown_type $headers
     * @param unknown_type $attachments
     */
    function send_mail($to, $subject, $message, $headers = '', $attachments = array()) {
        global $config_core;
        $maildelimiter = $config_core['maildelimiter'] == 1 ? "\r\n" : ($config_core['maildelimiter'] == 2 ? "\r" : "\n");
        if (!is_array($attachments))
            $attachments = explode($maildelimiter, $attachments);

        if (empty($headers)) {
            $headers = array();
        } else {
            if (!is_array($headers)) {
                $tempheaders = (array) explode($maildelimiter, $headers);
            } else {
                $tempheaders = $headers;
            }
            $headers = array();

            if (!empty($tempheaders)) {
                foreach ((array) $tempheaders as $header) {
                    if (strpos($header, ':') === false) {
                        if (false !== stripos($header, 'boundary=')) {
                            $parts = preg_split('/boundary=/i', trim($header));
                            $boundary = trim(str_replace(array("'", '"'), '', $parts[1]));
                        }
                        continue;
                    }
                    list( $name, $content ) = explode(':', trim($header), 2);

                    $name = trim($name);
                    $content = trim($content);

                    if ('from' == strtolower($name)) {
                        if (strpos($content, '<') !== false) {
                            $from_name = substr($content, 0, strpos($content, '<') - 1);
                            $from_name = str_replace('"', '', $from_name);
                            $from_name = trim($from_name);

                            $from_email = substr($content, strpos($content, '<') + 1);
                            $from_email = str_replace('>', '', $from_email);
                            $from_email = trim($from_email);
                        } else {
                            $from_email = trim($content);
                        }
                    } elseif ('content-type' == strtolower($name)) {
                        if (strpos($content, ';') !== false) {
                            list( $type, $charset ) = explode(';', $content);
                            $content_type = trim($type);
                            if (false !== stripos($charset, 'charset=')) {
                                $charset = trim(str_replace(array('charset=', '"'), '', $charset));
                            } elseif (false !== stripos($charset, 'boundary=')) {
                                $boundary = trim(str_replace(array('BOUNDARY=', 'boundary=', '"'), '', $charset));
                                $charset = '';
                            }
                        } else {
                            $content_type = trim($content);
                        }
                    } elseif ('cc' == strtolower($name)) {
                        $cc = explode(",", $content);
                    } elseif ('bcc' == strtolower($name)) {
                        $bcc = explode(",", $content);
                    } else {
                        $headers[trim($name)] = trim($content);
                    }
                }
            }
        }
        require_once CB_INCLUDE . '/mail.class.php';
        $mailer = new PHPMailer();
        $mailer->CharSet = CHARSET;
        $mailer->LE = $maildelimiter;
        if ($config_core['mailsend'] == 1) {
            $mailer->IsMail();
        } elseif ($config_core['mailsend'] == 2) {
            require_once CB_INCLUDE . '/smtp.class.php';
            $mailer->IsSMTP();
        }
        $mailer->Host = $config_core ['smtp_server'];
        $mailer->Port = $config_core ['smtp_port'] ? $config_core ['smtp_port'] : 25;
        $mailer->SMTPSecure = $config_core['smtp_secure'];
        $mailer->SMTPAuth = $config_core ['smtp_auth'] ? true : false;
        if ($mailer->SMTPAuth) {
            $mailer->Username = $config_core ['smtp_username'];
            $mailer->Password = $config_core ['smtp_password'];
        }
        $mailer->ClearAddresses();
        $mailer->ClearAllRecipients();
        $mailer->ClearAttachments();
        $mailer->ClearBCCs();
        $mailer->ClearCCs();
        $mailer->ClearCustomHeaders();
        $mailer->ClearReplyTos();
        // 发信人地址和姓名
        if (!isset($from_name)) {//如果headers中没的指定
            $from_name = $config_core['site_name'];
        }

        if (!isset($from_email)) {
            $from_email = $config_core['sendemail_address'];
        }

        $mailer->From = $from_email;
        $mailer->FromName = $from_name;
        $mailer->AddAddress($to);
        $mailer->Subject = $subject;
        $mailer->Body = $message;
        if (!empty($cc)) {
            foreach ((array) $cc as $recipient) {
                $mailer->AddCc(trim($recipient));
            }
        }
        if (!empty($bcc)) {
            foreach ((array) $bcc as $recipient) {
                $mailer->AddBcc(trim($recipient));
            }
        }

        if (!isset($content_type)) {
            $content_type = 'text/plain';
            //$content_type == 'text/html';
        }

        $mailer->ContentType = $content_type;

        if ($content_type == 'text/html') {
            $mailer->IsHTML(true);
        }

        if (!empty($headers)) {
            foreach ((array) $headers as $name => $content) {
                $mailer->AddCustomHeader(sprintf('%1$s: %2$s', $name, $content));
            }
            if (false !== stripos($content_type, 'multipart') && !empty($boundary)) {
                $mailer->AddCustomHeader(sprintf("Content-Type: %s;$maildelimiter\t boundary=\"%s\"", $content_type, $boundary));
            }
        }

        if (!empty($attachments)) {
            foreach ($attachments as $attachment) {
                $mailer->AddAttachment($attachment);
            }
        }
        $result = $mailer->Send();
        if ($result) {
            return true;
        } else {
            return $mailer->ErrorInfo;
        }
    }

    function ob_gzip($content) {
        if (!headers_sent() && extension_loaded("zlib") && strstr($_SERVER["HTTP_ACCEPT_ENCODING"], "gzip")) {
            $content = gzencode($content, 9);
            header("Content-Encoding: gzip");
            header("Vary: Accept-Encoding");
            header("Content-Length: " . strlen($content));
        }
        return $content;
    }

